import {ModelReferencer} from "./modelReferencing/ModelReferencer";
import {NotifyViewType} from "./view/UIBaseView";

/*
*ClassName:Model
*Description:数据层模型
*Date:2019/10/8 0:40
// */
export abstract class Model extends ModelReferencer {

    public static instances: Model[] = [];

    public static sortedInstances: Map<string, Model> = new Map<string, Model>();
    public static typeSortedInstances: Map<string, any[]> = new Map<string, any[]>();


    private onChangeHandlers: Function[] = [];
    private onDeleteHandlers: Function[] = [];

    public _id: string;//当前modelId
    public modelClassName: string;

    // public get getClassName(): string {
    //     return "modelClassName";
    // }

    protected static className;

    public static getName(): string {
        return this.className;
    }

    private isRegistered: boolean = false;

    public get id(): string {
        return this._id;
    }

    public set id(value: string) {
        this.Unregister();
        this._id = value;
        this.Register();
    }

    // public constructor(typeName:string ){
    //     super();
    //     this.typeName = typeName;
    //     this.Id = Date.now().toString();
    //     console.log("id = ", this.Id);
    // }

    public constructor(className: string,data ?: Object) {
        super();
        this.modelClassName = className;
        this.id = Date.now().toString();
        //console.log("id = ", this.Id);

        for (let i in  data) {
            if(data[i]){
                this[i] = data[i];
                //console.log("i ",i,"/data=", data[i]);
            }
        }
    }

    private Unregister() {
        if (!this.isRegistered) {
            return;
        }
        this.isRegistered = false;
        if (Model.sortedInstances.has(this._id)) {
            Model.sortedInstances.delete(this._id);
        }

        if (Model.typeSortedInstances.has(this.modelClassName)) {
            let index: number = Model.typeSortedInstances.get(this.modelClassName).indexOf(this);
            if (index >= 0) {
                Model.typeSortedInstances.get(this.modelClassName).splice(index, 1);
            }
        }

        let index: number = Model.instances.indexOf(this);
        if (index >= 0) {
            Model.instances.splice(index, 1);
        }
    }

    private Register() {
        if (this.isRegistered) {
            return;
        }
        this.isRegistered = true;

        if (!Model.sortedInstances.has(this._id)) {
            Model.sortedInstances.set(this._id, this);
        }

        //console.error("Model.sortedInstances?",Model.sortedInstances)

        if (!Model.typeSortedInstances.has(this.modelClassName)) {
            let model: Model[] = [];
            Model.typeSortedInstances.set(this.modelClassName, model);
        }
        Model.typeSortedInstances.get(this.modelClassName).push(this);

        Model.instances.push(this);
    }

    /**
     * 根据 id 查找Model
     * */
    public static FindModel(id: string): Model {
        if (!Model.sortedInstances.has(id)) {
            console.error("could not find model by id = ", id);
            return null;
        }
        return Model.sortedInstances.get(id);
    }

    /// <summary>
    /// 根据ID找到Model
    /// </summary>
    /// <typeparam name="T">Model类型</typeparam>
    /// <param name="id">Model ID</param>
    /// <returns>Model</returns>
    public static FindModelByT<T>(id: string): Model {
        let model: Model = Model.FindModel(id);
        // if (model.name !== T.name) {
        //     console.error("could not find model id =", id, " and type =", typeof T);
        //     return null;
        // }
        return model;
    }

    public static GetAllModelList<T extends Model>(model: ModelClass<T>): T[] {
        let models: T[] = [];
        if (!this.typeSortedInstances.has(model.getName())) {
            return models;
        }

        let typeList = this.typeSortedInstances.get(model.getName());
        for (let i = 0; i < typeList.length; i++) {
            models.push(typeList[i] as T);
        }
        return models;
    }

    public static GetModelById<T extends Model>(model: ModelClass<T>, id: string): T {
        let models: T[] = Model.GetAllModelList <T>(model);
        return models.find((info: any) => (info.id == id));
    }

    public static GetModelByType<T extends Model>(model: ModelClass<T>): T {
        let models: T[] = Model.GetAllModelList <T>(model);
        return models.find((info: any) => (info.getName() == model.getName()));
    }

    public Delete() {

    }

    public static DeleteAll() {
        Model.ReverseIterateList<Model>(Model.instances, (model: Model) => {
            model.Delete();
        });
    }

    public GetReferences(): Model[] {

        let references: Model[] = [];
        let modelReferencer: ModelReferencer[] = [];

        // List<Model> references = new List<Model>();
        // List<ModelReferencer> referencers = GetModelReferencersInFields();
        // foreach (ModelReferencer referencer in referencers) {
        //     references.AddList<Model>(referencer.GetReferences());
        // }
        // references.Distinct<Model>();
        return references;
    }

    /// <summary>
    /// 返回所有存在的Model
    /// </summary>
    /// <returns>返回所有存在的Model</returns>
    public static GetAll(): Model[] {
        return Model.instances;
    }

    public CollectReferences() {

    }

    /// <summary>
    /// 添加MODEL数据改变NotifyChange的监听事件
    /// </summary>
    /// <param name="callback">回调函数</param>
    public AddChangeListener(callback: Function) {
        if (callback == null) {
            console.error("Failed to add ChangeListener on Model but the given callback is null!");
            return;
        }

        let index: number = this.onChangeHandlers.indexOf(callback);
        if (index >= 0) {
            return;
        }
        this.onChangeHandlers.push(callback);
    }

    /***删除监听事件*/
    public RemoveChangeListener(callback: Function) {
        let index: number = this.onChangeHandlers.indexOf(callback);
        if (index >= 0) {
            this.onChangeHandlers.splice(index, 1);
        }
    }

    /// <summary>
    /// 添加MODEL数据改变NotifyChange的监听事件
    /// </summary>
    /// <param name="callback">回调函数</param>
    public AddDeleteListener(callback: Function) {
        if (callback == null) {
            console.error("Failed to add ChangeListener on Model but the given callback is null!");
            return;
        }

        let index: number = this.onDeleteHandlers.indexOf(callback);
        if (index >= 0) {
            return;
        }
        this.onDeleteHandlers.push(callback);
    }

    /***删除监听事件*/
    public RemoveDeleteListener(callback: Function) {
        let index: number = this.onDeleteHandlers.indexOf(callback);
        if (index >= 0) {
            this.onDeleteHandlers.splice(index, 1);
        }
    }

    /***发送数据变化*/
    public NotifyChange(type: NotifyViewType = NotifyViewType.update) {
        for (let i = 0; i < this.onChangeHandlers.length; i++) {
            let callBack: Function = this.onChangeHandlers[i];
            callBack && callBack(type);
        }
    }


    /**遍历执行方法*/
    public static ReverseIterateList<T>(list: T[], action: Function) {
        for (let i = list.length - 1; i >= 0; i--)
            action(list [i]);
    }

    public RemoveDeleteItemList(callback: any, list: any[]) {
        let index: number = list.indexOf(callback);
        if (index >= 0) {
            list.splice(index, 1);
        }
    }

    public static OnSetHash(str: string): string {
        let hash = 0;
        if (str.length == 0) return hash.toString();
        for (let i = 0; i < str.length; i++) {
            var char = str.charCodeAt(i);
            hash = ((hash << 5) - hash) + char;
            hash = hash & hash;
        }
        return hash.toString();
    }
}

export interface ModelClass<T extends Model> {
    new(): T;

    getName(): string;
}